import pandas as pd
import happybase
from pandas.io.json import json_normalize
import json


class AutoCarQuery:
    """
    自动驾驶数据查询对象
    """

    def __init__(self, table, identifier, msgcode, start, end=None):
        self._table = table
        self._identifier = identifier
        self._msgcode = msgcode
        self._starttime = self.convert_time(start)
        self._endtime = None if end is None else self.convert_time(end)

    @property
    def table(self):
        """
        [str] hbase表
        """
        return self._table

    @property
    def identifier(self):
        """
        [str] 车辆识别号
        """
        return self._identifier

    @property
    def msgcode(self):
        """
        [str] 消息类型
        """
        return self._msgcode

    @property
    def start_time(self):
        """
        [pd.datetime] 开始时间(带时区)
        """
        return self._starttime

    @property
    def end_time(self):
        """
        [pd.datetime] 结束时间(带时区)
        """
        return self._endtime

    @staticmethod
    def convert_time(timestr):
        time = pd.to_datetime(timestr)
        time = time.tz_localize('Asia/Shanghai')
        return time

    def __getRowkey(self, time):
        if time is None:
            return None
        else:
            timestr = str(9223372036854775807 - int(time.value / 10 ** 9))
            rowkey = (self._identifier + self._msgcode + timestr).encode()
            return rowkey

    # 由于key值设计时间范围相反
    def get_start_rowkey(self):
        return self.__getRowkey(self._endtime)

    def get_end_rowkey(self):
        return self.__getRowkey(self._starttime)


class BaseHbaseIO:
    def __init__(self, db_con):
        self._config = db_con
        self._engine = self.create_engine(db_con)

    def get_engine(self, config=None):

        if config is None:
            config = self._config
        if self._engine is None:
            self._engine = self.create_engine(config)
        return self._engine

    def create_engine(self, config):
        """
        使用happybase获取hbase连接
        :return:
        """
        # connection = happybase.Connection('10.2.111.56',9090)
        # connection = happybase.Connection(host="10.2.111.60",port=9090,timeout=None,
        #                                   autoconnect=True,table_prefix=None,table_prefix_separator=b'_',
        #                                   compat='0.98', transport='buffered',protocol='binary')

        ip = config['ip']
        port = config['port']
        connection = happybase.Connection(ip, port)
        return connection

    def query(self, autoCarQuery):
        """
         数据库查询操作
        :param autoCarQuery: 数据查询对象
        :return:
        """
        result = None
        try:
            engine = self.get_engine()
            t = engine.table(autoCarQuery.table)
            if autoCarQuery.end_time is None:
                row = t.row(autoCarQuery.get_end_rowkey())
                data = self.parse_dic_from_json(row)
                result = json_normalize(data)
                result.timestamp = self.series_to_timestamp(result.timestamp)
            else:
                scanResult = t.scan(row_start=autoCarQuery.get_start_rowkey(), row_stop=autoCarQuery.get_end_rowkey())
                list = []
                for key, value in scanResult:
                    data = self.parse_dic_from_json(value)
                    list.append(data)
                result = json_normalize(list)
                result.timestamp = self.series_to_timestamp(result.timestamp)
        except Exception as e:
            raise e
        return result

    def series_to_timestamp(self, series):
        series = pd.to_datetime(series, unit='ms')
        series = series.dt.tz_localize('UTC')
        series = series.dt.tz_convert('Asia/Shanghai')
        return series

    def parse_dic_from_json(self, res):
        res = json.loads(res[b'ivista:JSON'].decode())
        for dic in res['databeaninfo']:
            if dic['type'] == '02':
                data = dic['realdata']
                # df = json_normalize(data)
        return data


# test
if __name__ == '__main__':
    config = {'ip': '10.2.111.56', 'port': 9090}
    hbase = BaseHbaseIO(config)

    autoQuery = AutoCarQuery('t_ivista_auto_ca', '3ln6l5su1hr643138', '03', '2018-03-23 17:13:11',
                             '2018-04-17 10:25:18')
    re = hbase.query(autoQuery)
    print(len(re))

    autoQuery = AutoCarQuery('t_ivista_auto_ca', '3ln6l5su1hr643138', '03', '2018-04-17 10:11:30')
    re = hbase.query(autoQuery)
    print(re)
